/////////////////////////////////////////////////////////////////////////////
// Name:        keybinder.h
// Purpose:     Classes for binding keypresses to commands.
// Author:      Francesco Montorsi
// Modified:    for Code::Blocks by Pecan Heber
// Created:     2004/02/19
// Copyright:   (c) Aleksandras Gluchovas and (c) Francesco Montorsi
// Licence:     wxWidgets licence
/////////////////////////////////////////////////////////////////////////////
// RCS-ID:      $Id: menuutils.h 10413 2015-08-22 17:33:36Z pecanh $


#ifndef __WX_MENUUTILS_H__
#define __WX_MENUUTILS_H__

#ifdef __GNUG__
#pragma interface "menuutils.h"
#endif

// includes
#include "wx/panel.h"
#include "wx/dialog.h"
#include "wx/listbox.h"
#include "wx/treectrl.h"
#include "wx/string.h"
#include "keybinder.h"

//! Returns the ID of the first menu item with the given name which
//! is found inside the given menu bar.
//! 返回在给定菜单栏中找到的具有给定名称的第一个菜单项的ID.
//int /*-lf-WXDLLIMPEXP_KEYBINDER*/ wxFindMenuItem(wxMenuBar *, const wxString &strMenuItemName);

int wxFindMenuItem(wxMenuBar *, const wxString &strMenuItemName);
//-int FindMenuDuplicateCount(wxMenuBar *p, const wxString &str);
int FindMenuDuplicateItems(wxMenu* pMenu, wxString& rStr, int& rCount);
wxString GetFullMenuPath(int);

// some useful macros
// 某些有用的宏
#define wxSAFE_DELETE(x)					{ if (x) delete x; x = NULL; }
#define wxSAFE_DELETE_ARRAY(x)				{ if (x) delete [] x; x = NULL; }


//! The command type identifier for a wxMenuCmd.
//! wxMenuCmd的命令类型标识符.
#define wxMENUCMD_TYPE						0x1234


//! Represents a wxCmd which just generates a wxEVT_COMMAND_MENU_SELECTED
//! when is executed.
//! 表示一个wxCmd,它只在执行时生成所选的wxEVT_COMMAND_MENU.
//class /*-lf-WXDLLIMPEXP_KEYBINDER*/ wxMenuCmd : public wxCmd
//----------------------------------------------------------------------------
class wxMenuCmd : public wxCmd
// ---------------------------------------------------------------------------
{
	//! The menuitem which is connected to this command
	//! 连接到此命令的菜单项(menuitem)
	wxMenuItem *m_pItem;

public:
    // static
    // 静态

	//! The menubar used by #CreateNew.
	//! CreateNew使用的菜单栏.
	static wxMenuBar *m_pMenuBar;

	//! Sets the menubar which will be used to search the menu items
	//! with the IDs given to the #CreateNew function.
	//! 设置菜单栏,该菜单栏将用于搜索具有指定给'CreateNew'函数的ID的菜单项.
	static void SetMenuBar(wxMenuBar *p)
		{ m_pMenuBar = p; }

	//! Register this type of command into wxCmd static array.
	//! Also calls the #SetMenuBar function with the given pointer.
	//! 将此类型的命令注册到wxCmd静态数组中.
	//! 还使用给定指针调用SetMenuBar函数.
	static void Register(wxMenuBar *p)
		{ wxCmd::AddCmdType(wxMENUCMD_TYPE, wxMenuCmd::CreateNew);
			wxMenuCmd::SetMenuBar(p); }

	//! Creates a new wxMenuCmd with the given ID.
	//! Automatically searches into the #m_pMenuBar variable the.
	//+v0.3 Verify the cmdName along with the id since CodeBlocks
	// deletes/recreates menu items. Old menu pointers may be in array.
	//-v0.3 static wxCmd *CreateNew(int id);
	//
	// 使用给定的ID创建一个新的wxMenuCmd.
	// 自动搜索'm_pMenuBar'变量.
	// 由于CodeBlocks删除/重新创建菜单项,请验证cmdName和id.旧的菜单指针可能在数组中.
	static wxCmd *CreateNew(wxString cmdName, int id); //+v0.3
public:

	wxMenuCmd(wxMenuItem *p,
		const wxKeyBind &first,
		const wxString &name = wxEmptyString,
		const wxString &desc = wxEmptyString) :
		 wxCmd(first, p->GetId(), name, desc), m_pItem(p)
    {;}

	wxMenuCmd(wxMenuItem *p = NULL,
		const wxString &name = wxEmptyString,
		const wxString &desc = wxEmptyString)
    {
		m_pItem = p;
		m_strDescription = desc;
		m_strName = name;

		if (m_pItem)
			m_nId = m_pItem->GetId();
	}

	virtual ~wxMenuCmd() {}

public:

	virtual void DeepCopy(const wxCmd *p) {
		wxMenuCmd *m = (wxMenuCmd *)p;
		m_pItem = m->m_pItem;
		wxCmd::DeepCopy(p);
	}

	virtual wxCmd *Clone() const {
		wxCmd *ret = new wxMenuCmd();
		ret->DeepCopy(this);
		return ret;
	}

	virtual int GetType() const {
		return wxMENUCMD_TYPE;
	}

    static bool IsNumericMenuItem(wxMenuItem* pwxMenuItem); //v0.4.25


protected:

	//! Generates the wxEVT_COMMAND_MENU_SELECTED and sends it to the
	//! client event handler which is given as client.
	//!
	//! 生成所选的wxEVT_COMMAND_MENU并将其发送到作为客户端提供的客户端事件处理程序.
	//!
	void Exec(wxObject *origin, wxEvtHandler *client);

	//! Updates the associated menu item; in particularly, adds,
	//! removes or changes the first shortcut which is shown
	//! next to the menuitem label.
	//! The 2nd, 3rd, 4th... shortcuts cannot be shown in the
	//! menuitem label and they are thus not considered...
	//! (but they do still work !!!)
	//!
	//! 更新关联的菜单项,特别是添加,删除或更改显示在菜单项标签旁边的第一个快捷方式.
	//! 第二,第三,第四... 快捷方式不能在菜单项标签中显示,因此不考虑它们...
	//! (但它们仍然有效!!!)
	//!

	void Update(wxMenuItem* pMnuItem = 0);
	#if defined( __WXMSW__ )
	wxMenuItem* RebuildMenuitem(wxMenuItem* pMnuItem); //+v0.4.6
	#endif
};//wxMenuCmd

// ***************************************************************************
//                          wxMenuWalker
// ***************************************************************************
//! The base class for a generic tree-walker algorithm.
//! To perform your task, provide the implementation of the #OnMenuWalk
//! and #OnMenuItemWalk functions.
//!
//! 泛型树代步者算法的基类.
//! 要执行任务,请提供OnMenuWalk和OnMenuItemWalk函数的实现.
//
// class /*-lf-WXDLLIMPEXP_KEYBINDER*/ wxMenuWalker
// ----------------------------------------------------------------------------
class wxMenuWalker
// ----------------------------------------------------------------------------
{
protected:

	//! The nest level.
	//! 嵌套级别
	int m_nLevel;

public:
	wxMenuWalker() { m_nLevel=0; }
	virtual ~wxMenuWalker() {}

protected:

    // the core functions
    // 核心函数

	//! Starts to climb the tree  :-)
	//! This is the main function to be called when everything is
	//! ready to begin.
	//! For an explanation of the 'data' argument, see below.
	//!
	//! 开始爬树
	//! 这是当一切都准备好开始时要调用的主要函数.
	//! 有关'data'参数的解释,请参见下文.
	//!
	void Walk(wxMenuBar *p, void *data);

	void WalkMenu(wxMenuBar *p, wxMenu *, void *);
	void WalkMenuItem(wxMenuBar *p, wxMenuItem *, void *);


	//! Called when a wxMenu is found in the menu bar passed to #Walk(),
	//! or when a submenu is found by #WalkMenuItem().
	//! - The "p" argument is the pointer given to #Walk()
	//! - The "m" argument is the menu which has been found
	//! - The "data" argument is a pointer to something which was
	//!   given to #Walk() as 'data' argument (if the given menu is
	//!   a top level menu) or the pointer to something which was
	//!   returned by #OnMenuItemWalk, if this function is being
	//!   called by #WalkMenuItem.
	//! The returned value is passed to the #OnMenuItemWalk function
	//! for all the items in the contained menu and then it's deleted
	//! through #DeleteData().
	//!
	//! 当在传递给Walk()的菜单栏中找到wxMenu或当WalkMenuItem()找到子菜单时调用.
	//! -"p" 参数是指向Walk()的指针
	//! -"m" 参数是找到的菜单
	//! -"data" 参数是指向作为"data"参数(如果给定菜单是顶级菜单)给定给Walk()的某个对象的指针,
	//!    或者指向由OnMenuItemWalk返回的某个对象的指针(如果该函数由WalkMenuItem调用).
	//!
	//! 返回的值将传递给包含菜单中所有项的OnMenuItemWalk函数,然后通过DeleteData()将其删除.
	//!
	virtual void *OnMenuWalk(wxMenuBar *p, wxMenu *m, void *data) = 0;

	//! Called when a wxMenuItem is found inside a wxMenu.
	//! This works like #OnMenuWalk() but "data" is something which was
	//! given to the #WalkMenuItem (which is always the caller of this
	//! function).
	//! If the current menu item contains a submenu, the returned value
	//! is passed to #OnMenuWalk() or it's directly deleted...
	//!
	//! 在wxMenu中找到wxMenuItem时调用.
	//! 它的工作方式类似于OnMenuWalk(),但是'data'是给WalkMenuItem(它总是这个函数的调用者)的.
	//! 如果当前菜单项包含子菜单,则返回的值将传递给OnMenuWalk()或直接删除...
	//!
	virtual void *OnMenuItemWalk(wxMenuBar *p, wxMenuItem *m, void *data) = 0;

	//! Called when a wxMenu has been exausted and the nest level is going
	//! to be decreased. Default implementation does nothing.
	//!
	//! 当wxMenu已被检验并且嵌套级别将降低时调用.默认实现什么也不做.
	//!
	virtual void OnMenuExit(wxMenuBar *, wxMenu *, void *) {}

	//! Deletes the given 'data'.
	//! The derived class should pass to the OnMenuWalk/OnMenuWalkItem
	//! functions always the same type of structure/class in 'data'
	//! and in this function it should just cast the given pointer to
	//! that type and delete it.
	//!
	//! 删除给定的"data"参数.
	//! 派生类应该传递给OnMenuWalk/OnMenuWalkItem函数,在'data'中始终是相同类型的结构/类,
	//! 在这个函数中,它应该将给定的指针投射到该类型并将其删除.
	//!
	virtual void DeleteData(void *data) = 0;

    //v0.2 CodeBlocks has menu items starting with numerics that
    //v0.2 contain filename slashes. They crash wxCmdMenu.GetLabel()
    //
    // 代码块(CodeBlocks)的菜单项以包含文件名斜杠的数字开头.
    // 它们会在wxcmdmmenu.GetLabel()崩溃
    //
	bool IsNumericMenuItem(wxMenuItem* pwxMenuItem); //v0.2

};

// ***************************************************************************
//              wxExTreeItemData
// ***************************************************************************
//! The data associated to each node of a tree used by
//! - wxMenuTreeWalker
//! - wxKeyConfigPanel
//!
//! This is a simple class which just contains an additional field,
//! which can be used to store the ID of the menu item associated
//! with this tree item.
//! The ID should be unique among all the commands contained in the
//! same command collection so it should be enough to identify a wxCmd...
//!
//! 与wxMenuTreeWalker和wxKeyConfigPanel使用的树的每个节点关联的数据.
//! 这是一个简单的类,它只包含一个额外的字段,可以用来存储与此树项关联的菜单项的ID.
//! 在同一个命令集合中包含的所有命令中,ID应该是唯一的,因此它应该足以标识wxCmd...
//!
//class WXDLLIMPEXP_KEYBINDER wxExTreeItemData : public wxTreeItemData
// ----------------------------------------------------------------------------
class wxExTreeItemData : public wxTreeItemData
// ----------------------------------------------------------------------------
{
protected:
	int m_nMenuId;

public:
	wxExTreeItemData(int id = wxID_INVALID) : m_nMenuId(id) {}
	virtual ~wxExTreeItemData() {}

	void SetMenuItemId(int n) {
		m_nMenuId = n;
	}

	int GetMenuItemId() {
		return m_nMenuId;
	}
};

// ***************************************************************************
//                  wxMenuTreeWalker
// ***************************************************************************
//! A wxMenuWalker-derived class which uses the recursive capabilities
//! of the tree-walker algorithm to populate a wxTreeCtrl with a
//! structure identical to the given menubar.
//!
//! Each node of the wxTreeCtrl is associated with a wxExTreeItemData
//! object which contains the ID of the menuitem it represents
//! (for items representing the top level menus, wxID_INVALID is
//! contained).
//!
//! 一个wxMenuWalker派生类,它使用树walker算法的递归功能用与给定菜单栏相同的结构填充wxTreeCtrl.
//
// wxTreeCtrl的每个节点都与一个wxExTreeItemData对象相关联,
// 该对象包含它所表示的菜单项的ID(对于表示顶级菜单的项,包含wxID_INVALID).
//
// class WXDLLIMPEXP_KEYBINDER wxMenuTreeWalker : public wxMenuWalker
// ----------------------------------------------------------------------------
class wxMenuTreeWalker : public wxMenuWalker
// ----------------------------------------------------------------------------
{
	wxTreeCtrl *m_pTreeCtrl;
	wxTreeItemId m_root;

public:
	wxMenuTreeWalker() {}
	virtual ~wxMenuTreeWalker() {}


	//! Attaches the tree structure of the menubar in the given tree control
	//! using the given tree item as root.
	//!
	//! 使用给定的树项作为根,在给定的树控件中附加菜单栏的树结构.
	//!
	void FillTreeBranch(wxMenuBar *p, wxTreeCtrl *ctrl, wxTreeItemId branch);

	//! Works like #FillTreeBranch but this function also removes all the tree
	//! items (before starting) and then builds the root with the given label.
	//!
	//! 工作方式类似于#FillTreeBranch(填充树分支),
	//! 但此函数也会删除所有树项(启动前),然后使用给定的标签生成根.
	//!
	void FillTreeCtrl(wxMenuBar *p, wxTreeCtrl *ctrl,
                        const wxString &rootname = wxT("root"))
    {
		ctrl->DeleteAllItems();
		FillTreeBranch(p, ctrl, ctrl->AddRoot(rootname));
	}

protected:

	void *OnMenuWalk(wxMenuBar *p, wxMenu *, void *);
	void *OnMenuItemWalk(wxMenuBar *p, wxMenuItem *, void *);
	void DeleteData(void *data);
};

// ***************************************************************************
//                  wxExComboItemData
// ***************************************************************************
//! The data associated with each entry of the combobox given
//! to the wxMenuComboListWalker class.
//! Contains the array of labels of the menu items contained
//! into a wxMenu and their IDs.
//!
//! 与给定给wxMenuComboListWalker类的组合框的每个项相关联的数据.
//! 包含包含在wxMenu中的菜单项的标签数组及其id.
//
// class WXDLLIMPEXP_KEYBINDER wxExComboItemData : public wxClientData
// ----------------------------------------------------------------------------
class wxExComboItemData : public wxClientData
// ----------------------------------------------------------------------------
{
protected:
	wxArrayString m_arrStr;
	wxArrayLong m_arrID;

public:
	wxExComboItemData() {}
	virtual ~wxExComboItemData() {}

	int GetID(int n) const
 		{ return m_arrID[n]; }
	wxArrayString &GetCmdNameArr()
		{ return m_arrStr; }

	void Append(const wxString &name, int id)
		{ m_arrStr.Add(name); m_arrID.Add(id); }
	void SetID(int n, int id)
		{ m_arrID[n] = id; }
};

// ***************************************************************************
//                  wxMenuCombListWalker
// ***************************************************************************
//! A wxMenuWalker-derived class which fills the given wxComboBox
//! with items associated with wxExComboItemData classes.
//! The labels of the items of the wxComboBox are the titles of
//! the wxMenus (nested & non-nested) contained in the wxMenuBar
//! which is "walked".
//! The wxExComboItemData associated with these items contains the
//! list of the wxMenuItem contained into the relative wxMenu.
//!
//! wxMenuWalker派生类,用与wxExComboItemData类关联的项填充给定的wxComboBox.
//! wxComboBox项的标签是wxMenuBar中包含的wxMenus(嵌套和非嵌套)的标题,它是'walked'.
//! 与这些项关联的wxExComboItemData包含包含在相对wxMenu中的wxMenuItem的列表.
//!
//class WXDLLIMPEXP_KEYBINDER wxMenuComboListWalker : public wxMenuWalker
// ----------------------------------------------------------------------------
class wxMenuComboListWalker : public wxMenuWalker
// ----------------------------------------------------------------------------
{
	wxComboBox *m_pCategories;
	wxString m_strAcc;

public:
	wxMenuComboListWalker() {}
	virtual ~wxMenuComboListWalker() {}

	//! Inserts into the given combobox all the menus
	//! 在给定的组合框中插入所有菜单
	void FillComboListCtrl(wxMenuBar *p, wxComboBox *combo);

protected:

	void *OnMenuWalk(wxMenuBar *p, wxMenu *, void *);
	void *OnMenuItemWalk(wxMenuBar *p, wxMenuItem *, void *);
	void OnMenuExit(wxMenuBar *p, wxMenu *m, void *data);
 	void DeleteData(void *data);
};

// ***************************************************************************
//                  wxMenuShortcutWalker
// ***************************************************************************
//! An helper class which is used by wxKeyBinder to import the
//! wxMenuCmd associated to a menu bar.
//! This function uses the wxMenuWalker algorithm to create a
//! plain list of wxMenuCmd (without any hierarchical structure)
//! in the given array of wxCmd*.
//!
//! wxKeyBinder用来导入与菜单栏关联的wxMenuCmd的助手类.
//! 此函数使用wxMenuWalker算法在给定的wxCmd*数组中创建wxMenuCmd(不带任何层次结构)的简单列表.
//!
//class WXDLLIMPEXP_KEYBINDER wxMenuShortcutWalker : public wxMenuWalker
// ----------------------------------------------------------------------------
class wxMenuShortcutWalker : public wxMenuWalker
// ----------------------------------------------------------------------------
{
	wxCmdArray *m_pArr;

public:
	wxMenuShortcutWalker() {}
	virtual ~wxMenuShortcutWalker() {}


	// Starts the process.
	// 开始导入处理
	void ImportMenuBarCmd(wxMenuBar *p, wxCmdArray *arr) {
		m_pArr = arr;
		Walk(p, NULL);
	}


protected:

	void *OnMenuWalk(wxMenuBar *, wxMenu *, void *) { return NULL; }
	void *OnMenuItemWalk(wxMenuBar *p, wxMenuItem *, void *);
	void DeleteData(void *data);
};


#endif		// __WX_MENUUTILS_H__


